BZOJ4152【AMPPZ2014】The Captain <最短路>

Problem

【AMPPZ2014】The Captain


Description

给定平面上的 个点,定义 的费用为 ,求从 号点走到 号点的最小费用。

Input

第一行包含一个正整数 ( ),表示点数。
接下来 行,每行包含两个整数 , ( ),依次表示每个点的坐标。

Output

一个整数,即最小费用。

Sample Input

1
2
3
4
5
6
5
2 2
1 1
4 5
7 1
6 7

Sample Output

1
2

标签:最短路

Solution

一道比较基础的最短路变形。
不难发现,在一个凸壳上,如果走任意一条弦,显然没有直接沿着凸壳走优。
所以分别按 排两次序,相邻点连边,可得到一个图。在此图上跑最短路即可。
注意,此题卡 (大佬:不错啊,卡错误算法天经地义~)

Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#include <bits/stdc++.h>
#define MAX_N 200000
#define fir first
#define sec second
#define mp make_pair
#define pli pair<lnt,int>
using namespace std;
typedef long long lnt;
int n; lnt dis[MAX_N+5];
vector <int> G[MAX_N+5], E[MAX_N+5];
struct node {int id, x, y;} p[MAX_N+5];
bool cmpx(const node &a, const node &b) {return a.x < b.x;}
bool cmpy(const node &a, const node &b) {return a.y < b.y;}
void addedgex(int u, int v, int a, int b) {G[u].push_back(v), E[u].push_back(p[b].x-p[a].x);}
void addedgey(int u, int v, int a, int b) {G[u].push_back(v), E[u].push_back(p[b].y-p[a].y);}
void Dijkstra() {
memset(dis, 0x7f, sizeof dis), dis[1] = 0;
priority_queue <pli> que; que.push(mp(0LL, 1));
bool mrk[MAX_N+5]; memset(mrk, false, sizeof mrk);
while (!que.empty()) {
int u = que.top().sec; que.pop();
if (mrk[u]) continue; mrk[u] = true;
for (int i = 0; i < (int)G[u].size(); i++) {
int v = G[u][i]; lnt c = E[u][i];
if (mrk[v] || dis[u]+c > dis[v]) continue;
dis[v] = dis[u]+c, que.push(mp(-dis[v], v));
}
}
}
int main() {
scanf("%d", &n); for (int i = 1; i <= n; i++) p[i].id = i, scanf("%d%d", &p[i].x, &p[i].y);
sort(p+1, p+n+1, cmpx); for (int i = 1; i < n; i++) addedgex(p[i].id, p[i+1].id, i, i+1), addedgex(p[i+1].id, p[i].id, i, i+1);
sort(p+1, p+n+1, cmpy); for (int i = 1; i < n; i++) addedgey(p[i].id, p[i+1].id, i, i+1), addedgey(p[i+1].id, p[i].id, i, i+1);
Dijkstra(); printf("%lld", dis[n]); return 0;
}
------------- Thanks For Reading -------------
0%